home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / ma92.lha / Hooks / Hooks.txt < prev   
Encoding:
Text File  |  1992-03-08  |  8.7 KB  |  270 lines

  1. (c)  Copyright 1992 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice,
  3. and is provided "as is" without warranty of any kind, either expressed
  4. or implied.  The entire risk as to the use of this information is
  5. assumed by the user.
  6.  
  7.  
  8. Callback Hooks
  9.  
  10. by David Junod
  11.  
  12.  
  13. The callback features of Release 2 provide a standard means for
  14. applications to extend the functionality of libraries, devices, and
  15. their applications.  This standard makes it easy for the operating
  16. system to use custom modules from different high level programming
  17. languages as part of the operating system.  For example, the layers
  18. library, which takes care of treating a display as a series of layered
  19. regions, allows an application to attach a pattern function to a
  20. display layer.  Instead of filling in the background of a layer with
  21. the background color, the layers library calls the custom pattern
  22. function which fills in the layer display with a custom background
  23. pattern.
  24.  
  25.  
  26. Callback Hook Functions and Structures
  27.  
  28. An application passes a custom function in the form of a callback Hook
  29. (from <utility/hooks.h>):
  30.  
  31.  
  32.     /* Standard hook structure */
  33.     struct Hook
  34.     {
  35.         struct MinNode h_MinNode;
  36.         ULONG (*h_Entry)();     /* stub function entry point */
  37.         ULONG (*h_SubEntry)();  /* the custom function entry point */
  38.         VOID *h_Data;           /* owner specific */
  39.     };
  40.  
  41.  
  42.  
  43.     h_MinNode - This field is reserved for use by the module that will
  44.     call the Hook.
  45.  
  46.     h_Entry - This is the address of the Hook stub.  When the OS calls
  47.     a callback function, it puts parameters for the callback function
  48.     in CPU registers A0, A1, and A2.  This makes it tough for higher
  49.     level language programmers to use a callback function because most
  50.     higher level languages don't have a way to manipulate CPU registers
  51.     directly.  The solution is a stub function which first copies the
  52.     parameters from the CPU registers to a place where a high level
  53.     language function can get to them.   The stub function then calls
  54.     the callback function.  Typically, the stub pushes the registers
  55.     onto the stack in a specific order and the high level language
  56.     callback function pops them off the stack.
  57.  
  58.     h_SubEntry - This is the address of the actual callback function
  59.     that the application has defined.  The stub calls this function.
  60.  
  61.     h_Data - This field is for the application to use.  It could point
  62.     to a global storage structure that the callback function utilizes.
  63.  
  64. There is only one function defined in utility.library for callback
  65. functions.
  66.  
  67.  
  68. ULONG CallHookPkt(struct Hook *hook, VOID *object, VOID *paramPkt);
  69.                                A0          A2            A1
  70.  
  71. This function invokes a standard callback Hook function.
  72.  
  73.  
  74. Simple Callback Hook Usage
  75.  
  76. A Hook function must accept the following three parameters in these
  77. specific registers:
  78.  
  79.     A0  Pointer to the Hook structure.
  80.     A2  Pointer to an object to manipulate.  The object is context
  81.         specific.
  82.     A1  Pointer to a message packet.  This is also context specific.
  83.  
  84. For a callback function written in C, the parameters should appear in
  85. this order:
  86.  
  87.  
  88. myCallbackFunction(Pointer to Hook (A0),
  89.                    Pointer to Object (A2),
  90.                    Pointer to message (A1));
  91.  
  92.  
  93. This is because the standard C stub pushes the parameters onto the
  94. stack in the following order: A1, A2, A0.  The following assembly
  95. language routine is a callback stub for C:
  96.  
  97.  
  98.     INCLUDE 'exec/types.i'
  99.     INCLUDE 'utility/hooks.i'
  100.  
  101.     xdef        _hookEntry
  102.  
  103.     _hookEntry:
  104.         move.l  a1,-(sp)                ; push message packet pointer
  105.         move.l  a2,-(sp)                ; push object pointer
  106.         move.l  a0,-(sp)                ; push hook pointer
  107.         move.l  h_SubEntry(a0),a0       ; fetch actual Hook entry point ...
  108.         jsr     (a0)                    ; and call it
  109.         lea     12(sp),sp               ; fix stack
  110.         rts
  111.  
  112.  
  113. If your C compiler supports registerized parameters, your callback
  114. functions can get the parameters directly from the CPU registers
  115. instead of having to use a stub to push them on the stack.  The
  116. following C language routine uses registerized parameters to put
  117. parameters in the right registers.  This routine requires a C compiler
  118. that supports registerized parameters.
  119.  
  120.  
  121.     #include <exec/types.h>
  122.     #include <utility/hooks.h>
  123.  
  124.     #define     ASM     __asm
  125.     #define     REG(x)  register __ ## x
  126.  
  127.     /* This function converts register-parameter hook calling
  128.      * convention into standard C conventions.  It requires a C
  129.      * compiler that supports registerized parameters, such as
  130.      * SAS/C 5.xx or greater.
  131.      */
  132.     ULONG ASM hookEntry(REG(a0) struct Hook *h, REG(a2) VOID *o, REG(a1) VOID *msg)
  133.     {
  134.         return ((*h->h_SubEntry)(h, o, msg));
  135.     }
  136.  
  137. A callback function is executed on the context of the module that
  138. invoked it.  This usually means that callback functions cannot call
  139. functions that need to look at environment specific data.  For example,
  140. printf() needs to look at the current process's input and output
  141. stream.  Entities like Intuition have no input and output stream.  The
  142. limitations on a callback function depend heavily upon the subsystem
  143. that is using them.  See that subsystem's documentation for more
  144. information.
  145.  
  146. For the callback function to access any of its global data, it needs to
  147. make sure the CPU can find the function's data segment.  It does this
  148. by forcing the function to load the offset for the program's data
  149. segment into CPU register A4.  See your compiler documentation for
  150. details.
  151.  
  152. The following is a simple function that can be used as a callback Hook.
  153.  
  154.  
  155.     ULONG MyFunction (struct Hook *h, VOID *o, VOID *msg)
  156.     {
  157.         /* A SASC and Manx function that obtains access to the global data segment */
  158.         geta4();
  159.  
  160.         /* Debugging function to send a string to the serial port */
  161.         KPrintF("Inside MyFunction()\n");
  162.  
  163.         return (1);
  164.     }
  165.  
  166. The next step is to initialize the Hook for use.  This basically means
  167. that the fields of the Hook structure must be filled with appropriate
  168. values.
  169.  
  170. The following simple function initializes a Hook structure.
  171.  
  172.     /* This simple function is used to initialize a Hook */
  173.     VOID InitHook (struct Hook *h, ULONG (*func)(), VOID *data)
  174.     {
  175.         /* Make sure a pointer was passed */
  176.         if (h)
  177.         {
  178.             /* Fill in the hook fields */
  179.             h->h_Entry = (ULONG (*)()) hookEntry;
  180.             h->h_SubEntry = func;
  181.             h->h_Data = data;
  182.         }
  183.     }
  184.  
  185. The following is a simple example of initializing and using a callback
  186. Hook function.
  187.  
  188. /* hooks1.c
  189.  * Simple hook example
  190.  * Copyright (C) 1991 Commodore-Amiga, Inc.
  191.  *
  192.  */
  193.  
  194. #include <exec/types.h>
  195. #include <exec/libraries.h>
  196. #include <utility/hooks.h>
  197. #include <clib/exec_protos.h>
  198. #include <clib/utility_protos.h>
  199.  
  200. extern struct Library *SysBase;
  201. struct Library *UtilityBase;
  202.  
  203. #define ASM     __asm
  204. #define REG(x)  register __ ## x
  205.  
  206. /* This function converts register-parameter Hook calling
  207.  * convention into standard C conventions.  It requires a C
  208.  * compiler that supports registerized parameters, such as
  209.  * SAS/C 5.xx or greater.
  210.  */
  211. ULONG ASM
  212. hookEntry(REG(a0) struct Hook *h, REG(a2) VOID *o, REG(a1) VOID *msg)
  213. {
  214.     return ((*h->h_SubEntry)(h, o, msg));
  215. }
  216.  
  217. /* This simple function is used to initialize a Hook */
  218. VOID InitHook (struct Hook *h, ULONG (*func)(), VOID *data)
  219. {
  220.     /* Make sure a pointer was passed */
  221.     if (h)
  222.     {
  223.         /* Fill in the Hook fields */
  224.         h->h_Entry = (ULONG (*)()) hookEntry;
  225.         h->h_SubEntry = func;
  226.         h->h_Data = data;
  227.     }
  228. }
  229.  
  230. /* This function only prints out a message to the serial port indicating that
  231.  * we are inside the callback function.  Note that we cannot use printf() or
  232.  * any other functions that use standard I/O with any of the system modules that
  233.  * support callback Hooks, because there is no guarantee that there would
  234.  * be a valid Output() channel. */
  235.  
  236. ULONG MyFunction (struct Hook *h, VOID *o, VOID *msg)
  237. {
  238.     /* Obtain access to the global data segment */
  239.     geta4();
  240.  
  241.     /* Debugging function to send a string to the serial port */
  242.     KPrintF("Inside MyFunction()\n");
  243.  
  244.     return (1);
  245. }
  246.  
  247. int main (int argc, char **argv)
  248. {
  249.     struct Hook h;
  250.  
  251.     /* Open the utility library */
  252.     if (UtilityBase = OpenLibrary ("utility.library", 36))
  253.     {
  254.         /* Initialize the callback Hook */
  255.         InitHook (&h, MyFunction, NULL);
  256.  
  257.         /* Use the utility library function to invoke the Hook */
  258.         CallHookPkt (&h, NULL, NULL);
  259.  
  260.         /* Close utility library now that we're done with it */
  261.         CloseLibrary (UtilityBase);
  262.     }
  263.     else
  264.     {
  265.         /* Display an error message */
  266.         printf ("Couldn't open utility.library\n");
  267.     }
  268. }
  269.  
  270. ยง